#pragma once

#include <iostream>
#include <queue>
#include <string>
#include <unistd.h>
#include <pthread.h>
#include <time.h>

namespace ns_thread_pool
{
    const int default_thread_num = 3;
    template <class T>
    class ThreadPool
    {
    private:
        std::queue<T> _task_queue;
        int _thread_num;
        pthread_mutex_t _mtx;
        pthread_cond_t _cond;

    public:
        ThreadPool(int thread_num = default_thread_num)
            : _thread_num(thread_num)
        {
            pthread_mutex_init(&_mtx, nullptr);
            pthread_cond_init(&_cond, nullptr);
        }
        ~ThreadPool();
        void Lock()
        {
            pthread_mutex_lock(&_mtx);
        }
        void Unlock()
        {
            pthread_mutex_unlock(&_mtx);
        }
        void Wait()
        {
            pthread_cond_wait(&_cond, &_mtx);
        }

        void Wakeup()
        {
            pthread_cond_signal(&_cond);
        }
        bool is_empty()
        {
            return _task_queue.empty();
        }
        static void *thread_run(void *args)
        {
            pthread_detach(pthread_self());
            ThreadPool<T> *tp = (ThreadPool<T> *)args;
            while (true)
            {
                int data = 0;
                tp->Pop(&data);
                std::cout << "子线程处理了一个值 " << data << std::endl;
                sleep(1);
            }
        }

        void InitThreadPool()
        {
            pthread_t tid;
            for (int i = 0; i < default_thread_num; i++)
            {
                pthread_create(&tid, nullptr, thread_run, (void *)this);
            }
        }

    public:
        void Push(const T &in)
        {
            Lock();
            _task_queue.push(in);
            UnLock();
            Wakeup();
        }
        void Pop(T *out)
        {
            Lock();
            while (is_empty())
            {
                Wait();
            }
            *out = _task_queue.front();
            _task_queue.pop();
            Unlock();
        }
    };
}
